package pers.whj.net.local.task;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;

public class FileInfo {
    private String mFileName;
    private String mFilePath;
    private final boolean mIsFile;
    private long mFileLength;
    private List<FileInfo> mFiles;

    public FileInfo(String filePath, boolean isFile, long fileLength) {
        filePath = normalizePath(filePath);
        mFileName = getNameByPath(filePath);
        mFilePath = filePath;
        mIsFile = isFile;
        mFileLength = fileLength;
        if (!isFile) {
            mFiles = new ArrayList<>();
        }
    }

    public static String normalizePath(String path) {
        if (path != null) {
            path = path.replaceAll("/+", Matcher.quoteReplacement(File.separator));
            path = path.replaceAll("\\\\+", Matcher.quoteReplacement(File.separator));
            int length = path.length();
            if (length > 0 && path.charAt(length - 1) == '\\') {
                path = path.substring(0, length - 1);
            }
        }
        return path;
    }

    public static String getNameByPath(String path) {
        String name = null;
        if (path != null) {
            String[] result = path.split("\\\\");
            int size = result.length;
            if (result[size - 1].equals("") && size > 1) {
                name = result[size - 2];
            } else {
                name = result[size - 1];
            }
        }
        return name;
    }

    public String getFileName() {
        return mFileName;
    }

    public String getFilePath() {
        return mFilePath;
    }

    public long getFileLength() {
        return mFileLength;
    }

    public boolean isFile() {
        return mIsFile;
    }

    public boolean isDirectory() {
        return !mIsFile;
    }

    public void setFilePath(String filePath) {
        normalizePath(filePath);
        mFileName = getNameByPath(filePath);
        mFilePath = filePath;
    }

    public void setFileLength(long fileLength) {
        mFileLength = fileLength;
    }

    public boolean isValidFile() {
        return mFilePath != null && mFileName != null;
    }

    public boolean hasFileInfo(FileInfo fileInfo) {
        if (fileInfo != null && fileInfo.isValidFile() && isValidFile() && !mIsFile) {
            if (mFiles != null) {
                for (FileInfo tmp : mFiles) {
                    if (tmp.getFilePath().equals(fileInfo.getFilePath()) && tmp.isFile() == fileInfo.isFile()) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    public void addFileInfo(FileInfo fileInfo) {
        if (fileInfo != null && !mIsFile && isValidFile() && fileInfo.isValidFile()) {
            if (fileInfo.getFilePath().equals(mFilePath + File.separatorChar + fileInfo.getFileName())) {
                if (!hasFileInfo(fileInfo)) {
                    mFiles.add(fileInfo);
                }
            } else {
                for (FileInfo tmp : mFiles) {
                    if (tmp.isDirectory() && fileInfo.getFilePath().startsWith(tmp.getFilePath())) {
                        tmp.addFileInfo(fileInfo);
                        break;
                    }
                }
            }
        }
    }

    public FileInfo[] listFiles() {
        FileInfo[] result = null;
        if (isDirectory() && mFiles != null) {
            result = new FileInfo[mFiles.size()];
            for (int i = 0; i < result.length; i++) {
                result[i] = mFiles.get(i);
            }
        }
        return result;
    }

    public List<FileInfo> listOnlyFilesInSubPath() {
        List<FileInfo> fileList = new ArrayList<>();
        listOnlyFiles(fileList, this);
        return fileList;
    }

    private void listOnlyFiles(List<FileInfo> list, FileInfo fileInfo) {
        if (fileInfo != null && fileInfo.isValidFile()) {
            FileInfo[] tmpList = fileInfo.listFiles();
            List<FileInfo> tmpDirectoryList = new ArrayList<>();
            if (tmpList != null) {
                for (FileInfo tmp : tmpList) {
                    if (tmp.isFile()) {
                        list.add(tmp);
                    } else {
                        tmpDirectoryList.add(tmp);
                    }
                }
                for (FileInfo tmp : tmpDirectoryList) {
                    listOnlyFiles(list, tmp);
                }
            }
        }
    }
}